package tazadum.engine.text;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import tazadum.engine.math.Quad;
import tazadum.engine.math.Vector;

public class Text {
	public static int SIZE = 8;
	private static final int SPACING = 0;

	private static final int[][] letters = { { 0, 0, 0, 0, 0, 0, 0, 0 }, // <space>
			{ 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c }, // 0
			{ 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c }, // 1
			{ 0x3e, 0x40, 0x40, 0x40, 0x3c, 0x2, 0x2, 0x7e }, // 2
			{ 0x3e, 0x40, 0x40, 0x3c, 0x40, 0x40, 0x40, 0x3e }, // 3
			{ 0x48, 0x44, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x40 }, // 4
			{ 0x7e, 0x2, 0x2, 0x3e, 0x40, 0x40, 0x40, 0x3e }, // 5
			{ 0x7c, 0x2, 0x2, 0x3e, 0x42, 0x42, 0x42, 0x3c }, // 6
			{ 0x3e, 0x20, 0x20, 0x78, 0x20, 0x20, 0x20, 0x20 }, // 7
			{ 0x3c, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c }, // 8
			{ 0x3c, 0x42, 0x42, 0x3c, 0x40, 0x40, 0x40, 0x3c }, // 9
			{ 0x7e, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42 }, // A
			{ 0x3e, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x3e }, // B
			{ 0x7c, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x7c }, // C
			{ 0x1e, 0x22, 0x42, 0x42, 0x42, 0x42, 0x22, 0x1e }, // D
			{ 0x7e, 0x2, 0x2, 0x1e, 0x2, 0x2, 0x2, 0x7e }, // E
			{ 0x7e, 0x2, 0x2, 0x1e, 0x2, 0x2, 0x2, 0x2 }, // F
			{ 0x7c, 0x2, 0x2, 0x2, 0x7a, 0x42, 0x42, 0x3c }, // G
			{ 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42 }, // H
			{ 0x3e, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x3e }, // I
			{ 0x7e, 0x40, 0x40, 0x40, 0x42, 0x42, 0x42, 0x3c }, // J
			{ 0x22, 0x12, 0xa, 0x6, 0xa, 0x12, 0x22, 0x42 }, // K
			{ 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x7e }, // L
			{ 0x42, 0x66, 0x5a, 0x42, 0x42, 0x42, 0x42, 0x42 }, // M
			{ 0x41, 0x43, 0x45, 0x49, 0x51, 0x61, 0x41, 0x41 }, // N
			{ 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c }, // O
			{ 0x7e, 0x42, 0x42, 0x42, 0x7e, 0x2, 0x2, 0x2 }, // P
			{ 0x3c, 0x42, 0x42, 0x42, 0x42, 0x52, 0x22, 0x5c }, // Q
			{ 0x3e, 0x42, 0x42, 0x22, 0x1e, 0x22, 0x42, 0x42 }, // R
			{ 0x3c, 0x42, 0x2, 0x3c, 0x40, 0x40, 0x42, 0x3c }, // S
			{ 0xfe, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, // T
			{ 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c }, // U
			{ 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x14, 0x8 }, // V
			{ 0x41, 0x41, 0x41, 0x41, 0x49, 0x55, 0x63, 0x41 }, // W
			{ 0x81, 0x42, 0x24, 0x10, 0x8, 0x24, 0x42, 0x81 }, // X
			{ 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x10 }, // Y
			{ 0x7e, 0x20, 0x10, 0x8, 0x4, 0x2, 0x7e, 0x0 }, // Z
	};

	public static byte[] toByteArray(final char ch) {
		final int n = translate(ch);
		final int[] letter = letters[n];

		final byte[] array = new byte[64];
		for (int y = 0; y < SIZE; y++) {
			for (int x = 0; x < SIZE; x++) {
				array[y * SIZE + x] = (byte) ((letter[y] & (1 << x)) > 0 ? 1 : 0);
			}
		}
		return array;
	}

	public static Collection<Quad> toQuads(final char ch, final float xScale, final float yScale, final float xOffset, final float yOffset) {
		final int n = translate(ch);
		final int[] letter = letters[n];

		final Collection<Quad> collection = new ArrayList<Quad>();
		for (int y = 0; y < SIZE; y++) {
			final float y0 = y * yScale + yOffset;
			final float y1 = y0 + yScale;
			for (int x = 0; x < SIZE; x++) {
				if ((letter[y] & (1 << x)) > 0) {
					final float x0 = x * xScale + xOffset;
					final float x1 = x0 + xScale;
					collection.add(new Quad(new Vector(x0, y0, 0), new Vector(x1, y0, 0), new Vector(x1, y1, 0), new Vector(x0, y1, 0)));
				}
			}
		}
		return collection;
	}

	public static Collection<Quad> toQuads(final String string, final float xScale, final float yScale, float xOffset, final float yOffset) {
		final Collection<Quad> collection = new LinkedList<Quad>();
		for (int i = 0; i < string.length(); i++) {
			collection.addAll(toQuads(string.charAt(i), xScale, yScale, xOffset, yOffset));
			xOffset += (SIZE + SPACING) * xScale;
		}
		return collection;
	}

	public static Collection<Vector> toVectors(final char ch, final float xScale, final float yScale, final float xOffset,
			final float yOffset) {
		final int n = translate(ch);
		final int[] letter = letters[n];

		final Collection<Vector> collection = new ArrayList<Vector>();
		for (int y = 0; y < SIZE; y++) {
			for (int x = 0; x < SIZE; x++) {
				if ((letter[y] & (1 << x)) > 0) {
					final float x0 = x * xScale + xOffset;
					final float y0 = y * yScale + yOffset;
					collection.add(new Vector(x0, y0, 0));
				}
			}
		}
		return collection;
	}

	public static List<Vector> toVectors(final String string, final float xScale, final float yScale, float xOffset, final float yOffset) {
		final List<Vector> collection = new LinkedList<Vector>();
		for (int i = 0; i < string.length(); i++) {
			collection.addAll(toVectors(string.charAt(i), xScale, yScale, xOffset, yOffset));
			xOffset += (SIZE + SPACING) * xScale;
		}
		return collection;
	}

	private static int translate(final char ch) {
		final int n = Character.toTitleCase(ch);
		if ('0' <= n && n <= '9') {
			return n - '0' + 1;
		}
		if ('A' <= n && n <= 'Z') {
			return n - 'A' + 11;
		}
		return 0;
	}
}
